package com.lagou.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author: jie.zhao
 * @create: 2021/06/28 19:25
 */
@Activate(group = {CommonConstants.CONSUMER,CommonConstants.PROVIDER})
public class TPMonitorFilter implements Filter {

    List<MethodInfo> methodInfos = new ArrayList<>();

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        String methodName = invocation.getMethodName();
        if(CollectionUtils.isEmpty(methodInfos)){
            printTP();
        }
        long   startTime  = System.currentTimeMillis();
        try {
            // 执行方法
            return  invoker.invoke(invocation);
        } finally {

            long endTime = System.currentTimeMillis();
            long costTime = endTime - startTime;
            //添加到集合
            methodInfos.add(new MethodInfo(methodName,costTime,endTime));
        System.out.println("invoke time:"+costTime + "毫秒");
        }

    }

    private void printTP(){

        ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
        pool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                //这个业务逻辑需要很长的时间，定时任务去统计一张数据上亿的表，财务财务信息，需要30min
                System.out.println("TP99:"+getTP(methodInfos,0.99));
                System.out.println("TP90:"+getTP(methodInfos,0.9));
            }
        },1,5, TimeUnit.SECONDS);
    }

    // rate 代表百分比 90 传入 0.9 即可  99 就是 0.99
    private  long  getTP(List<MethodInfo> methodInfos,double  rate){
        // System.out.println("getTp");
        // 构建一个临时数组保存 满足1一分钟之内的数据
        List<MethodInfo>  sortInfo = new ArrayList<MethodInfo>();
        // 计算最近一分钟的TP90 和 TP99
        long  endTime = System.currentTimeMillis();
        long  startTime = System.currentTimeMillis() - 60000;
        // 遍历列表集合
        int  length = methodInfos.size();
        for (int i=0;i<length;i++){
            //System.out.println("#######");
            MethodInfo  methodInfo = methodInfos.get(i);
            if (methodInfo.getEndTimes() >= startTime && methodInfo.getEndTimes() <= endTime){
                sortInfo.add(methodInfo);
            }
        }
        sortInfo.sort(new Comparator<MethodInfo>() { //正序排列

            public int compare(MethodInfo o1, MethodInfo o2) {
                if(o1.getTimes() > o2.getTimes()){
                    return  1;
                }else if(o1.getTimes() < o2.getTimes()){
                    return -1;
                }else{
                    return  0;
                }

            }
        });
        int  index = (int)(sortInfo.size() * rate);//直接取整

        return sortInfo.get(index).getTimes();
    }



}
